<template>
    <el-dialog v-if="visible" :visible.sync="visible" :title="title ? title : void 0" :show-close="false" :close-on-press-escape="false">
        <span v-html="tips" style="white-space: break-spaces"></span>
        <div class="loading">
            <div class="loading-box">
                <div class="loading-animate"></div>
                <div class="loading-countdown" v-if="showTime" id="confirmDialog_countdown">{{ time }}</div>
            </div>
        </div>
    </el-dialog>
</template>

<script>
import i18n from '@/lang';

export default {
    name: 'countDown',

    data() {
        return {
            // 打开倒计时，调用时默认打开
            visible: true,

            // 倒计时定时器
            timer: null,

            // 倒计时时间，默认 30 秒
            time: 30,

            // 是否成功提示
            success: true,

            // 弹窗标题
            title: '',

            /**
             * @description 配置对象
             * @param end 倒计时结束回调函数
             * @param tips 倒计时弹窗提示语
             * @param polling 如果需要在倒计时过程中执行一个函数，接受一个polling对象，至少包含 callback 执行函数及 stop 停止条件数组
             * @param toast 倒计时结果，赋值即显示
             */
            options: {},

            // 提示信息
            tips: '',

            // 是否显示倒计时数字
            showTime: true
        };
    },

    methods: {
        startCountdown() {
            let startTime = Date.now();

            let startCount = this.time;

            if (!this.timer) {
                this.timer = setInterval(async () => {
                    this.time = startCount - parseInt((Date.now() - startTime) / 1000);

                    this.time = this.time < 0 ? 0 : this.time;

                    // 判断是否有需要在倒计时进行过程中执行的函数
                    if ('polling' in this.options) {
                        const polling = this.options['polling'];

                        const callback = polling['callback'];

                        const stop = polling['stop'];

                        // 判断执行函数及停止条件是否存在
                        if (!('callback' in polling) || !('stop' in polling)) {
                            this.success = false;
                            this.stopCountDown();
                            throw new Error('执行函数或停止条件不存在');
                        }

                        // 判断 callback 是否函数
                        if (typeof callback != 'function') {
                            this.success = false;
                            this.stopCountDown();
                            throw new Error('callback 不是可执行函数');
                        }

                        // 判断 break 是否数组
                        if (!Array.isArray(stop)) {
                            this.success = false;
                            this.stopCountDown();
                            throw new Error('stop 不是数组');
                        }

                        let res = '';

                        if ('callbackType' in polling && polling['callbackType'] == 'sync') {
                            // 执行同步函数
                            res = callback(this.time);
                        } else {
                            // 执行异步函数
                            res = await callback(this.time);
                        }

                        // 动态根据结果设置 tips
                        if ('tips' in polling && polling['tips'][res]) {
                            this.tips = polling['tips'][res];
                        }

                        // 根据传入的停止倒计时条件判断是否需要停止轮询
                        if (stop.includes(res)) {
                            this.success = false;
                            this.stopCountDown();
                            return;
                        }
                    }

                    // 倒计时结束
                    if (this.time <= 0) {
                        this.stopCountDown();
                    }
                }, 1000);
            } else {
                this.stopCountDown();
            }
        },

        // 停止倒计时
        stopCountDown() {
            clearInterval(this.timer);

            this.timer = null;

            this.visible = false;

            // 倒计时回调
            if ('end' in this.options) {
                this.options.end(this.time);
            }

            if ('toast' in this.options) {
                let propResult = void 0;

                if ('success' in this.options) {
                    propResult = this.options['success'];
                } else {
                    propResult = this.success;
                }

                const result = propResult ? 'success' : 'error';

                this.$message[result](i18n.t(`common.${result}`));
            }
        },

        // 设置是否显示倒计时数字
        setShowTime() {
            if ('showTime' in this.options) {
                this.showTime = this.options['showTime'];
            }
        },

        // 设置弹窗标题
        setTitle() {
            if ('title' in this.options) {
                this.title = this.options['title'];
            }
        },

        // 设置提示信息
        setMessage() {
            if ('tips' in this.options) {
                this.title = i18n.t('login.reason_tips');

                return (this.tips = this.options['tips']);
            }

            return (this.tips = '');
        }
    },

    // 默认开启倒计时
    mounted() {
        this.setShowTime();

        this.setMessage();

        this.setTitle();

        this.startCountdown();
    }
};
</script>

<style scoped lang="less">
@import '@/assets/css/theme_blue/common.less';
@import '@/assets/css/theme_blue/component_common.less';
@import '@/assets/css/theme_blue/component_round.less';

.loading {
    &-box {
        position: relative;
        margin: 12px auto 0px;
        width: 62px;
        height: 62px;
        box-sizing: border-box;
    }
    &-countdown {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-size: 16px;
        font-weight: 600;
    }
    &-animate {
        position: absolute;
        top: 0px;
        left: 0px;
        width: 56px;
        height: 56px;
        border: 3px solid @blueColor;
        border-top-color: transparent;
        border-radius: 50%;
        animation: rotate 1s linear infinite;
    }
}
@keyframes rotate {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(360deg);
    }
}
</style>
